iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
Modern Web

PixiJS青銅玩家系列 第 26

【LV. 26】PixiJS青銅玩家:helper function - keyboard()(3)abc?

  • 分享至 

  • xImage
  •  

▉ 前言

這裡將利用教程所提供的"Treasure Hunter Game"來直接學習PixiJS中的語法。"Treasure Hunter Game"的程式碼 ---> Click Here !

系統提示:「If winter comes , can spring be far behind ?--P. B. Shelley」,PixiJS青銅玩家還卡關於自定義function階段,僅獲得經驗提昇等級。

▉ 主線任務:helper function - keyboard( )之abc

▍任務說明

abc分別是apply()、bind()、call(),雖然說apply()、call()要綁在一起講,順序有點不對,但是這樣對我來說比較好記(常常忘記他們的名稱)

所以這次的任務就是要從自定義函數keyboard中來認識abc家族(?)

▍作法

function keyboard(keyCode) {
  var key = {};
  key.code = keyCode;
  key.isDown = false;
  key.isUp = true;
  key.press = undefined;
  key.release = undefined;
  //The `downHandler`
  key.downHandler = function(event) {
    if (event.keyCode === key.code) {
      if (key.isUp && key.press) key.press();
      key.isDown = true;
      key.isUp = false;
    }
    event.preventDefault();
  };

  //The `upHandler`
  key.upHandler = function(event) {
    if (event.keyCode === key.code) {
      if (key.isDown && key.release) key.release();
      key.isDown = false;
      key.isUp = true;
    }
    event.preventDefault();
  };

  //Attach event listeners
  window.addEventListener(
    "keydown", key.downHandler.bind(key), false
  );
  window.addEventListener(
    "keyup", key.upHandler.bind(key), false
  );
  return key;
}

▍分析

主要是以下這個部份,因此想了解下bind(),也連帶順便認識一下apply()call()

window.addEventListener(
    "keydown", key.downHandler.bind(key), false
);
window.addEventListener(
    "keyup", key.upHandler.bind(key), false
);

***

先來看看MDN以及ECMAScript上對於this的解釋:

  1. MDN

  2. ECMAScript

感覺上this就是一個很靈活的小東西,在不同情況下,他可以指向不同的值。

apply()call()bind()這三個函式都是用來改變this指向的對象,或者說可以綁定this指向的對象。

***

所以我想從this綁定開始寫起,其他應該先不會研究。
關於this的綁定,有四種方法:

  1. 預設綁定
  2. 隱含綁定
  3. 明確綁定
  4. new運算子綁定

至於apply()call()bind()被歸類在明確綁定的部份,其他可能只會簡單的先帶過。

***

1. 預設綁定

  • 指向:全域(依執行環境可能指向global或window)
  • 舉例:
    • In browser
      我在瀏覽器中的devtool建立一個函數叫做person()

      會發現此時的this會指向window
    • In nodejs
      如果換成利用nodejs執行

      就會發現this指向global
    • "use strict"
      這個稱為嚴格模式,如果使用這個模式,this值就會變成"undefined"

2. 隱含綁定

  • 指向:用來呼叫該函數的物件

  • 舉例:

    結果如下

    可以從上方執行的函式觀察到,最後執行的兩段程式差異性:

    person1.whatYourName();
    sayYourName();
    

    第一段:我們利用物件person1的屬性來呼叫sayYourName(),此時的this指向的是「呼叫該函數的物件」,也就是person1

    所以當執行sayYourName()裡面的console.log後,印出來的this.name就會是person1中的name

    第二段:直接執行sayYourName(),此時的this指向的是全域,但是全域中沒有name屬性啊,所以得到的就會是"undefine"。

3. 明確綁定

  • 指向:apply()call()bind()的參數
  • 舉例:
    • apply() & call()
      這兩個一起講,因為太相似了。

      • call()
        先來看看call()

        可以傳入兩個參數,第一個參數可以改變this指向的內容、後面的參數則依序為function test的參數a,b,c所要帶入的內容。
        印出結果如下
      • apply()
        接著是apply()

        call()一樣,第一個參數傳入this要指向的對象,不同的是傳入function test的參數方式,apply()是利用陣列來作為參數傳入。
        當然結果與call()都是一樣的
    • bind()
      我們先看下面這段程式碼:

      印出的結果為

      直接執行func()得到結果為"undefined"的原因,是因為執行func()時,this指向的會是全域(這跟我們呼叫的方法有關),所以就會想是不是有辦法讓我們可以設立一個函數,不管怎麼呼叫,他的this都不會改變,於是bind()就誕生了!


      此時利用bind(),將sayYourName()裡面的this與person1綁在一起,因此當我需要this.name時,他就會去找person1中的屬性name了,並且把他儲存成一個函數,之後我們就可以直接使用這個函數,也不必擔心this出什麼差錯,而指向不如我們預期的東西。

      對了,還是印出一下結果

      ***

      怕命名上有點混淆,所以這邊改一下上方範例:

      印出結果如下

4. new運算子綁定

  • 指向:新建構的物件
  • 舉例:因為本來就打算只講apply()call()bind(),所以這裡就...不繼續寫了(加上我沒時間了QAQ)

***

回到Treasure Hunter Game

window.addEventListener(
    "keydown", key.downHandler.bind(key), false
);

當"keydown"被觸發時,則執行key.downHandler.bind(key),而他這邊做的事情就是把key物件中的屬性downHandler()中的this指向綁定到key本身身上,如此一來downHandler()這個函式就可以取用key物件中的屬性去使用。


▉ 結語

從物件導向概念、this概念,再到apply()call()bind(),今天花了大概5個小時的時間不間斷的去理解,幸好有生出來(不然就白蹺課了),也把一直有點逃避的內容給理解起來,儘管還是很不熟悉,但是比過去有更懂了些!

今天是用Treasure Hunter Game官方教程來寫鐵人賽的最後一天,然而鐵人賽還有4天,究竟後面幾天能不能熬過去(突然發現這好像不是能不能的問題...因為一定要撐完)

目前規劃剩下27,28,29天會分別來寫遊戲相關的擴充內容:(雖然也不保證當天有沒有辦法生出來就是了,但是會盡力!)

  1. 人物移動仍然置中於遊戲畫面
  2. 人物走動時會換圖
  3. 場景的跳轉(類似換關卡的概念)
  4. 場景中的障礙物設置

至於第30天當然就拿來寫心得啦¯_(ツ)_/¯


參考資料


上一篇
【LV. 25】PixiJS青銅玩家:helper function - keyboard()(3)事件
下一篇
【LV. 27】PixiJS青銅玩家:讓角色行動但置中於地圖(1)
系列文
PixiJS青銅玩家30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言